<?php

/*
 * This script belongs to Aspect PHP.
 *
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * This script is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-
 * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details.
 */

/**
 * A bunch of utils method for Aspect PHP
 *
 * @package    aspectPhp
 * @subpackage lib
 * @author     gboisse
 */
class aspectUtils {

    /**
     * Parses the annotations of the given comments
     *
     * @param  string $docComment The doc block to scan for annotations
     * @return array
     */
    public static function parseAnnotations($docComment) {
        $annotations = array();

        if (preg_match_all('/@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?$/m', $docComment, $matches)) {
            $numMatches = count($matches[0]);

            for ($i = 0; $i < $numMatches; ++$i) {
                $annotations[$matches['name'][$i]][] = $matches['value'][$i];
            }
        }

        return $annotations;
    }

    /**
     * Parses the given arguments pattern to a readable array
     *
     * @param string $arguments
     * @return array
     */
    public static function parseArgumentsPatternToArray($arguments) {
        if (empty($arguments)) {
            return array();
        }

        $arguments = explode(',', $arguments);
        $arguments = array_map('trim', $arguments);

        $parsedArguments = array();
        foreach ($arguments as $argument) {
            preg_match_all('/^(?P<variable>[\S]+) *(?P<compare>==|\>=|\>|\<=|\<|!=)(?P<value>.*)$/', $argument, $matches);
            if (!isset($matches['variable'][0]) || !isset($matches['compare'][0]) || !isset($matches['value'][0])) {
                throw new InvalidArgumentException("Illegal argument identifier '$argument'!");
            }
            if (preg_match('/\'/', $argument)) {
                throw new InvalidArgumentException("Do not use simple quote for argument evaluation: '$argument'! Prefer double quotes!");
            }
            $variable = $matches['variable'][0];
            $compare = $matches['compare'][0];
            $value = trim($matches['value'][0]);

            $parsedArguments[$variable] = ' ' . $compare . ' ' . $value;
        }

        return $parsedArguments;
    }

    /**
     * Calls the given callback function
     *
     * @param  mixed $callback The callback function
     * @param  mixed $arguments The arguments of the function
     * @return mixed The result of the execution of the function
     */
    public static function callFunction($callback, $arguments) {
        if (!is_callable($callback)) {
            throw new RuntimeException('Aspect unable to call '
                    . get_class($callback[0]) . '->' . $callback[1] . '()!');
        }

        if (is_array($arguments)) {
            return call_user_func_array($callback, $arguments);
        } else {
            return call_user_func($callback, $arguments);
        }
    }

    /**
     * Returns a camelized string from a lower case and underscored string
     *
     * @param  string $lower_case_and_underscored_word The string to camelize
     * @return string Camelized string
     */
    public static function camelize($lower_case_and_underscored_word) {
        $result = $lower_case_and_underscored_word;
        $result = self::pregtr($result, array('#/(.?)#e' => "'::'.strtoupper('\\1')",
                    '/(^|_|-)+(.)/e' => "strtoupper('\\2')"));

        return $result;
    }

    /**
     * Returns subject replaced with regular expression matchs
     *
     * @param mixed $search Subject to search
     * @param array $replacePairs Array of search => replace pairs
     */
    public static function pregtr($search, $replacePairs) {
        return preg_replace(array_keys($replacePairs), array_values($replacePairs), $search);
    }

}
